﻿body = document.body;
view = document.getElementById("view");
workspace = document.getElementById("workspace");
codespace = document.getElementById("codespace");
source = document.getElementById("source");

Array.prototype.__defineGetter__("x", function() { return this[0]; });
Array.prototype.__defineSetter__("x", function(v) { this[0] = v; });
Array.prototype.__defineGetter__("y", function() { return this[1]; });
Array.prototype.__defineSetter__("y", function(v) { this[1] = v; });
Array.prototype.__defineGetter__("z", function() { return this[2]; });
Array.prototype.__defineSetter__("z", function(v) { this[2] = v; });
Array.prototype.__defineGetter__("w", function() { return this[3]; });
Array.prototype.__defineSetter__("w", function(v) { this[3] = v; });

Array.prototype.__defineGetter__("r", function() { return this[0]; });
Array.prototype.__defineSetter__("r", function(v) { this[0] = v; });
Array.prototype.__defineGetter__("g", function() { return this[1]; });
Array.prototype.__defineSetter__("g", function(v) { this[1] = v; });
Array.prototype.__defineGetter__("b", function() { return this[2]; });
Array.prototype.__defineSetter__("b", function(v) { this[2] = v; });
Array.prototype.__defineGetter__("a", function() { return this[3]; });
Array.prototype.__defineSetter__("a", function(v) { this[3] = v; });


width = 400;
height = 400;
	
pause = true;
frameCount = 0;

function play() {
    pause = false;
}

function stop() {
    pause = true;
}

function loop() {
	render();
}

function loopDelegate() {
    if(pause) return;
    loop();
    frameCount++;
}

timer = setInterval(loopDelegate, 1000 / 30);

canvas = document.getElementById("canvas");
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
view.appendChild(canvas);

exportspace = document.getElementById("exportspace");
exportspace.style.left = window.innerWidth - 100 + "px";
exportspace.style.top = "0px";

imgData = ctx.createImageData(width, height);

function setPixel(imageData, x, y, c) {
    index = (x + y * imageData.width) * 4;
    imageData.data[index+0] = parseInt(clamp(c[0] * 255, 0, 255));
    imageData.data[index+1] = parseInt(clamp(c[1] * 255, 0, 255));
    imageData.data[index+2] = parseInt(clamp(c[2] * 255, 0, 255));
    imageData.data[index+3] = parseInt(clamp(c[3] * 255, 0, 255));
}

function shader(x, y) {
	return [255, 255, 255, 0];
}

function render() {
	for(var y = 0; y < height; y++) {
		var fy = y / (height - 1);
		for(var x = 0; x < width; x++) {
			var fx = x / (width - 1);
			var c = shader(fx, fy);
			setPixel(imgData, x, y, c);
		}
	}
	ctx.putImageData(imgData, 0, 0);
}

function size(w, h) {
    width = w;
    height = h;
    view.style.width = width + "px";
	view.style.height = height + "px";
	view.style.left = window.innerWidth * 0.5 - view.offsetWidth * 0.5 + "px";
	view.style.top = window.innerHeight * 0.5 - view.offsetHeight * 0.5 + "px"; 
	canvas.width = width;
	canvas.height = height;
	delete imgData;
	imgData = ctx.createImageData(width, height);
}

function arrangeView() {
	view.style.width = width + "px";
	view.style.height = height + "px";
	//view.style.left = window.innerWidth * 0.5 - view.offsetWidth * 0.5 + "px";
	view.style.top = window.innerHeight * 0.5 - view.offsetHeight * 0.5 + "px";
	view.style.left = source.offsetWidth + 10 + "px";	
}

window.onresize = function(evt) {
	arrangeView();
	exportspace.style.left = window.innerWidth - 100 + "px";
	exportspace.style.top = "0px";
}


function init() {
	var btRender = document.getElementById("render");
	var btPlay = document.getElementById("play");
	var btStop = document.getElementById("stop");
	var btExport = document.getElementById("export");
	
	btExport.onclick = function() {
		var src = canvas.toDataURL();
		var img = document.createElement("img");
		img.src = src;
		img.style.width = "100px";
		img.style.height = "100px";
		exportspace.insertBefore(img, exportspace.childNodes[0]);
	}
	
	btRender.onclick = function() {
		frameCount = 0;
		runScript();
		render();
		arrangeView();
	}
	
	btPlay.onclick = function() {
		runScript();
		play();
		arrangeView();
	}

	btStop.onclick = function() {
		stop();
	}
	
	/*
	var so = document.getElementById("so");
	so.style.width = "50px";
	source.style.opacity = so.value / 100;
	so.onchange = function(evt) {
		source.style.opacity = evt.target.value / 100;
	}
	*/
	
	source.style.width = "300px";
	source.style.height = "200px";
	arrangeView();
	/*
	if(window.localStorage['source'] != undefined) {
		source.value = window.localStorage['source'];
		show();
	}
	else {
		source.value = "c = circle(200, 200, 100);";
		//hide();
	}
	*/
	source.value = "function shader(x, y) {\n\
    v = sin(x * PI * 5);\n\
    return [v, v, v, 1];\n\}";
	runScript();
	render();
}

function show() {
	workspace.style.visibility = "visible";
}

function hide() {
	workspace.style.visibility = "hidden";
}

function runScript() {
	if(codespace.childNodes.length > 0) {
		codespace.removeChild(codespace.childNodes[0]);
	}
	var script = document.createElement("script");
	script.type = "text/javascript";
	script.textContent = document.getElementById("source").value;
	codespace.appendChild(script);
}

function clear() {
	
}

function random(min, max) {
	
	if(arguments.length > 2) { 
		throw errNofArgs; 
		return;
	}
	
	for(var i in arguments) {
		if(isNaN(arguments[i])) {
			throw errNaN;
			return;
		}
	}
	
	if(arguments.length == 0) { 
		return Math.random();
	}
	
	if(arguments.length == 1) { 
		return Math.random() * min;
	}
	
	if(arguments.length == 2) { 
		return Math.random() * (max - min) + min;
	}
}

function saturate(x) {
	return clamp(x, 0, 1);
}

function step(a, x) {
	return (x >= a) ? 1 : 0;
}

function smoothstep(a, b, x) {
  x = saturate((x - a) / (b - a));
  return x*x*(3-2*x);
}

function pulse(a, b, fuzz, x) {
  return smoothstep(a, a + fuzz, x) - smoothstep(b - fuzz, b, x);
}

function mod(a, b) {
  var n = parseInt(a/b);
  a -= n * b;
  if(a < 0) a+= b;
  return a;
}

function length(v) {
	return Math.sqrt(dot(v, v));
}

function normalize(v) {
	var d = length(v);
	if( d > 0) {
		for(var i = 0; i < v.length; i++) {
			v[i] = v[i] / d; 
		}
	}
	return v;
}

function dot(a, b) {
	var result = 0;
	for(var i = 0; i < a.length; i++) {
		result += a[i] * b[i]; 
	}
	return result;
}

function dot(a, b) {
	var result = 0;
	for(var i = 0; i < a.length; i++) {
		result += a[i] * b[i]; 
	}
	return result;
}

function cross(a, b) {
	if(a.length == 2) return (a.x*b.y) - (a.y*b.x);
	return [a.y*b.z - a.z*b.y, a.z*b.y - a.x*b.z, a.x*b.y - a.y*b.x];
}

function bias(b, x) {
    return Math.pow(x, Math.log(b)/LOG05);
}

function gain(g, x) {
    if (x < 0.5)
        return bias(1-g, 2*x)/2;
    else
        return 1 - bias(1-g, 2 - 2*x)/2;
}

function repeat(x, freq) {
  return mod(x * freq, 1.0);
}

function clamp(x, min, max) {
    if(x < min) x = min;
    if(x > max) x = max;
    return x;
}

function wrap(x, min, max) {
    if(x < min) x = max;
    if(x > max) x = min;
    return x;
}

function dist(x0, y0, x1, y1) {
	var dx = x0 - x1;
	var dy = y0 - y1;
	return Math.sqrt(dx*dx + dy*dy);
	return Math.sqrt(dx*dx + dy*dy);
}

function lerp(a, b, x) {
	return (1 - x) * a + x * b;
}

function radians(x) {
	return x / 180 * Math.PI;
}

function degrees(x) {
	return x / Math.PI * 180;
}

function checkTab(evt) {
	var tab = "    ";
    var t = evt.target;
    var ss = t.selectionStart;
    var se = t.selectionEnd;
    // Tab key - insert tab expansion
    if (evt.keyCode == 9) {
        evt.preventDefault();
                
        // Special case of multi line selection
        if (ss != se && t.value.slice(ss,se).indexOf("\n") != -1) {
            // In case selection was not of entire lines (e.g. selection begins in the middle of a line)
            // we ought to tab at the beginning as well as at the start of every following line.
            var pre = t.value.slice(0,ss);
            var sel = t.value.slice(ss,se).replace(/\n/g,"\n"+tab);
            var post = t.value.slice(se,t.value.length);
            t.value = pre.concat(tab).concat(sel).concat(post);
                    
            t.selectionStart = ss + tab.length;
            t.selectionEnd = se + tab.length;
        }
                
        // "Normal" case (no selection or selection on one line only)
        else {
            t.value = t.value.slice(0,ss).concat(tab).concat(t.value.slice(ss,t.value.length));
            if (ss == se) {
                t.selectionStart = t.selectionEnd = ss + tab.length;
            }
            else {
                t.selectionStart = ss + tab.length;
                t.selectionEnd = se + tab.length;
            }
        }
    }
}

source.onkeydown = function(evt) {
	checkTab(evt);
}

function save(){
	window.localStorage['source'] = source.value;
	window.localStorage['timestamp'] = (new Date()).getTime();
}
//--------------- Math
E = 2.718281828459045;
LN2 = 0.6931471805599453;
LOG05 = -0.6931371805599453;
LN10 = 2.302585092994046;
LOG2E = 1.4426950408889634;
LOG10E = 0.43429448190325176;
PI = 3.141592653589793;
SQRT1_2 = 0.7071067811865476;
SQRT2 = 1.4142135623730951;
function abs(x) { return Math.abs(x); }
function acos(x) { return Math.acos(x); }
function asin(x) { return Math.asin(x); }
function atan(x) { return Math.atan(x); }
function atan2(y, x) { return Math.atan2(y, x); }
function ceil(x) { return Math.ceil(x); }
function cos(x) { return Math.cos(x); }
function exp(x) { return Math.exp(x); }
function floor(x) { return Math.floor(x); }
function log(x) { return Math.log(x); }
function max(x, y) { return Math.max(x, y); }
function min(x, y) { return Math.min(x, y); }
function pow(x, y) { return Math.pow(x, y); }
function round(x) { return Math.round(x); }
function sin(x) { return Math.sin(x); }
function sign(x) { if(x > 0) return 1; if(x < 0) return -1; return 0; }
function sqrt(x) { return Math.sqrt(x); }
function tan(x) { return Math.tan(x); }
function sinh(x) { return (Math.exp(x) - Math.exp(-x)) / 2.0;}
function cosh(x) { return (Math.exp(x) + Math.exp(-x)) / 2.0;}
function tanh(x) { return (Math.exp(2*x) - 1) / (Math.exp(2*x) + 1);}
function coth(x) { return (Math.exp(2*x) + 1) / (Math.exp(2*x) - 1);}
function sech(x) { return 2 / (Math.exp(x) + Math.exp(-x));}
function csch(x) { return 2 / (Math.exp(x) - Math.exp(-x));}
//--------------- Noise
var sinLUT = [];
var cosLUT = [];
var SINCOS_PRECISION = 0.5;
var SINCOS_LENGTH = parseInt(360 / SINCOS_PRECISION);

var PERLIN_YWRAPB = 4;
var PERLIN_YWRAP = 1 << PERLIN_YWRAPB;
var PERLIN_ZWRAPB = 8;
var PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB;
var PERLIN_SIZE = 4095;

var perlin_octaves = 4; // default to medium smooth
var perlin_amp_falloff = 0.5; // 50% reduction/octave

var perlin_TWOPI, perlin_PI;
var perlin_cosTable = [];
var perlin = [];

function buildSinCosLUT() {
	for (var i = 0; i < SINCOS_LENGTH; i++) {
		sinLUT.push(Math.sin(radians(i * SINCOS_PRECISION)));
		cosLUT.push(Math.cos(radians(i * SINCOS_PRECISION)));
	}
}

function noise(x, y, z) {
	if(arguments.length == 3) return pnoise(x, y, z);
	if(arguments.length == 2) return pnoise(x, y, 0);
	if(arguments.length == 1) return pnoise(x, 0, 0);
}

function pnoise(x, y, z) {
	if (perlin.length == 0) {
		buildSinCosLUT();

		for (var i = 0; i < PERLIN_SIZE + 1; i++)
		{
			perlin.push(random(1));
		}

		perlin_cosTable = cosLUT;
		perlin_TWOPI = perlin_PI = SINCOS_LENGTH;
		perlin_PI >>= 1;
	}

	if (x < 0) x = -x;
	if (y < 0) y = -y;
	if (z < 0) z = -z;

	var xi = Math.floor(x);
	var yi = Math.floor(y);
	var zi = Math.floor(z);
	var xf = (x - xi);
	var yf = (y - yi);
	var zf = (z - zi);
	var rxf = 0;
	var ryf = 0;

	var r = 0;
	var ampl = 0.5;

	var n1, n2, n3;

	for (var i = 0; i < perlin_octaves; i++)
	{
		var of = Math.floor(xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB));

		rxf = noise_fsc(xf);
		ryf = noise_fsc(yf);

		n1 = perlin[of & PERLIN_SIZE];
		n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1);
		n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
		n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2);
		n1 += ryf * (n2 - n1);

		of += PERLIN_ZWRAP;
		n2 = perlin[of & PERLIN_SIZE];
		n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2);
		n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
		n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3);
		n2 += ryf * (n3 - n2);

		n1 += noise_fsc(zf) * (n2 - n1);

		r += n1 * ampl;
		ampl *= perlin_amp_falloff;
		xi <<= 1; xf *= 2;
		yi <<= 1; yf *= 2;
		zi <<= 1; zf *= 2;

		if (xf >= 1.0) { xi++; xf--; }
		if (yf >= 1.0) { yi++; yf--; }
		if (zf >= 1.0) { zi++; zf--; }
	}
	return r;
}

function noise_fsc(i) {
	var n = Math.floor(i * perlin_PI) % perlin_TWOPI;
	if (n > perlin_cosTable.length - 1) n = perlin_cosTable.length - 1;
	if (n < 0) n = 0;
	var v = 0;
	v = perlin_cosTable[n];
	return 0.5 * (1.0 - v);
}

function noiseDetail(lod, falloff) {
	if (lod > 0) perlin_octaves = lod;
	if (falloff > 0) perlin_amp_falloff = falloff;
}
//-------------------- https://gist.github.com/304522
/*
var SimplexNoise = function(r) {
	if (r == undefined) r = Math;
  this.grad3 = [[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0], 
                                 [1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1], 
                                 [0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]]; 
  this.p = [];
  for (var i=0; i<256; i++) {
	  this.p[i] = Math.floor(r.random()*256);
  }
  // To remove the need for index wrapping, double the permutation table length 
  this.perm = []; 
  for(var i=0; i<512; i++) {
		this.perm[i]=this.p[i & 255];
	} 

  // A lookup table to traverse the simplex around a given point in 4D. 
  // Details can be found where this table is used, in the 4D noise method. 
  this.simplex = [ 
    [0,1,2,3],[0,1,3,2],[0,0,0,0],[0,2,3,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,2,3,0], 
    [0,2,1,3],[0,0,0,0],[0,3,1,2],[0,3,2,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,3,2,0], 
    [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0], 
    [1,2,0,3],[0,0,0,0],[1,3,0,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,3,0,1],[2,3,1,0], 
    [1,0,2,3],[1,0,3,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,0,3,1],[0,0,0,0],[2,1,3,0], 
    [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0], 
    [2,0,1,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,0,1,2],[3,0,2,1],[0,0,0,0],[3,1,2,0], 
    [2,1,0,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,1,0,2],[0,0,0,0],[3,2,0,1],[3,2,1,0]]; 
};

SimplexNoise.prototype.dot = function(g, x, y) { 
	return g[0]*x + g[1]*y;
};

SimplexNoise.prototype.noise = function(xin, yin) { 
  var n0, n1, n2; // Noise contributions from the three corners 
  // Skew the input space to determine which simplex cell we're in 
  var F2 = 0.5*(Math.sqrt(3.0)-1.0); 
  var s = (xin+yin)*F2; // Hairy factor for 2D 
  var i = Math.floor(xin+s); 
  var j = Math.floor(yin+s); 
  var G2 = (3.0-Math.sqrt(3.0))/6.0; 
  var t = (i+j)*G2; 
  var X0 = i-t; // Unskew the cell origin back to (x,y) space 
  var Y0 = j-t; 
  var x0 = xin-X0; // The x,y distances from the cell origin 
  var y0 = yin-Y0; 
  // For the 2D case, the simplex shape is an equilateral triangle. 
  // Determine which simplex we are in. 
  var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords 
  if(x0>y0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1) 
  else {i1=0; j1=1;}      // upper triangle, YX order: (0,0)->(0,1)->(1,1) 
  // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and 
  // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where 
  // c = (3-sqrt(3))/6 
  var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords 
  var y1 = y0 - j1 + G2; 
  var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords 
  var y2 = y0 - 1.0 + 2.0 * G2; 
  // Work out the hashed gradient indices of the three simplex corners 
  var ii = i & 255; 
  var jj = j & 255; 
  var gi0 = this.perm[ii+this.perm[jj]] % 12; 
  var gi1 = this.perm[ii+i1+this.perm[jj+j1]] % 12; 
  var gi2 = this.perm[ii+1+this.perm[jj+1]] % 12; 
  // Calculate the contribution from the three corners 
  var t0 = 0.5 - x0*x0-y0*y0; 
  if(t0<0) n0 = 0.0; 
  else { 
    t0 *= t0; 
    n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0);  // (x,y) of grad3 used for 2D gradient 
  } 
  var t1 = 0.5 - x1*x1-y1*y1; 
  if(t1<0) n1 = 0.0; 
  else { 
    t1 *= t1; 
    n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1); 
  }
  var t2 = 0.5 - x2*x2-y2*y2; 
  if(t2<0) n2 = 0.0; 
  else { 
    t2 *= t2; 
    n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2); 
  } 
  // Add contributions from each corner to get the final noise value. 
  // The result is scaled to return values in the interval [-1,1]. 
  return 70.0 * (n0 + n1 + n2); 
};

// 3D simplex noise 
SimplexNoise.prototype.noise3d = function(xin, yin, zin) { 
  var n0, n1, n2, n3; // Noise contributions from the four corners 
  // Skew the input space to determine which simplex cell we're in 
  var F3 = 1.0/3.0; 
  var s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D 
  var i = Math.floor(xin+s); 
  var j = Math.floor(yin+s); 
  var k = Math.floor(zin+s); 
  var G3 = 1.0/6.0; // Very nice and simple unskew factor, too 
  var t = (i+j+k)*G3; 
  var X0 = i-t; // Unskew the cell origin back to (x,y,z) space 
  var Y0 = j-t; 
  var Z0 = k-t; 
  var x0 = xin-X0; // The x,y,z distances from the cell origin 
  var y0 = yin-Y0; 
  var z0 = zin-Z0; 
  // For the 3D case, the simplex shape is a slightly irregular tetrahedron. 
  // Determine which simplex we are in. 
  var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords 
  var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords 
  if(x0>=y0) { 
    if(y0>=z0) 
      { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order 
      else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order 
      else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order 
    } 
  else { // x0<y0 
    if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } // Z Y X order 
    else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } // Y Z X order 
    else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } // Y X Z order 
  } 
  // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), 
  // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and 
  // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where 
  // c = 1/6.
  var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords 
  var y1 = y0 - j1 + G3; 
  var z1 = z0 - k1 + G3; 
  var x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords 
  var y2 = y0 - j2 + 2.0*G3; 
  var z2 = z0 - k2 + 2.0*G3; 
  var x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords 
  var y3 = y0 - 1.0 + 3.0*G3; 
  var z3 = z0 - 1.0 + 3.0*G3; 
  // Work out the hashed gradient indices of the four simplex corners 
  var ii = i & 255; 
  var jj = j & 255; 
  var kk = k & 255; 
  var gi0 = this.perm[ii+this.perm[jj+this.perm[kk]]] % 12; 
  var gi1 = this.perm[ii+i1+this.perm[jj+j1+this.perm[kk+k1]]] % 12; 
  var gi2 = this.perm[ii+i2+this.perm[jj+j2+this.perm[kk+k2]]] % 12; 
  var gi3 = this.perm[ii+1+this.perm[jj+1+this.perm[kk+1]]] % 12; 
  // Calculate the contribution from the four corners 
  var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0; 
  if(t0<0) n0 = 0.0; 
  else { 
    t0 *= t0; 
    n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0, z0); 
  }
  var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1; 
  if(t1<0) n1 = 0.0; 
  else { 
    t1 *= t1; 
    n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1, z1); 
  } 
  var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2; 
  if(t2<0) n2 = 0.0; 
  else { 	
    t2 *= t2; 
    n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2, z2); 
  } 
  var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3; 
  if(t3<0) n3 = 0.0; 
  else { 
    t3 *= t3; 
    n3 = t3 * t3 * this.dot(this.grad3[gi3], x3, y3, z3); 
  } 
  // Add contributions from each corner to get the final noise value. 
  // The result is scaled to stay just inside [-1,1] 
  return 32.0*(n0 + n1 + n2 + n3); 
};

Noise = new SimplexNoise();
function noise(x, y, z) {
	return Noise.noise3d(x, y, z);
}
*/

init();